#include "votesys.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
#define LOGFILE "vote.log"
#define GID 103 

countList list;
uidList uList;

bool_t isVoteOpen = TRUE;


static void 
unmarshal_submitvote(char *lm, NetMessage *msg)
{
  if(msg == NULL || lm == NULL )
    return;

  strcpy(lm, msg->data);
}


static void
marshal_submitvote(voteStatus status, NetMessage *msg, char* token)
{
   if( msg == NULL ) 
     return;
   sprintf(msg->data, "%d %s", status, token); 
}


static void
marshal_results(countList *l, NetMessage *msg)
{
  int i;
  char tmp[MAXSTLEN];
  if( l == NULL || msg == NULL )
    return;

  if(l->num == 0)
  {
    msg->length = 0;
    return;
  }

  for(i=0; i<(l->num); i++)
  {
     sprintf(tmp,"%s %d" ,(l->array[i]).name, (l->array[i]).count);
     strcat(msg->data, tmp);    
     (msg->length)++;
  } 
}


static void 
vlog_result()
{
  FILE *f;
  time_t timer;
  u_long i;
  timer = time(NULL);
  f = fopen(LOGFILE, "a");
  
  fprintf(f, "election terminating at %s",
           asctime( localtime(&timer)) );
  for(i=0; i<list.num; i++)
  {
    fprintf(f, " %d vote(s) %s\n", list.array[i].count, list.array[i].name); 
  }
  fclose(f);
}


bool_t
closevote_1_svc(void *x, void *y, struct svc_req *rqstp)
{
   
   if ( rqstp->rq_cred.oa_flavor == AUTH_SYS )
   {
      struct authsys_parms *au;

      au = (struct authsys_parms *) rqstp->rq_clntcred;

      /*Check user's gid*/
      if ( au->aup_gid == GID )
      {
       isVoteOpen = FALSE; 
       vlog_result();
       return TRUE;
      }

   }

   return FALSE; 
}


static void 
wlog(char *name, char *token)
{
   FILE *f;       
   time_t timer;
   f = fopen(LOGFILE, "a");
   timer = time(NULL); 
   fprintf(f, "vote for %s -token %s at %s", name, token, asctime(localtime(&timer)));
   fclose(f);
}



/*generate a token*/
static void 
genToken(char *token)
{
  long i;
  srand((unsigned int)time(NULL));
  sprintf(token, "%s%d", tempnam(".",NULL)+2, rand()%999999);
}



bool_t 
vote_1_svc(NetMessage *nm, NetMessage *stat, struct svc_req *rqstp)
{
  
  long i, num;

  char artist[MAXLENDATA]; 
  char token[MAXLENTOKEN];
  voteStatus status;
  struct authsys_parms *au;
  FILE *fp;

  au = (struct authsys_parms *) rqstp->rq_clntcred;

  unmarshal_submitvote(artist, nm);

  if( isVoteOpen == FALSE )
  {
    status = vsInvalidVoter;
    marshal_submitvote(status, stat, "");
    return TRUE;
  }

  /*Check user's uid*/
  for(i=0; i<uList.num; i++)
  {
     if ( au->aup_uid == uList.uids[i] )
       return FALSE;  
  }

  num = list.num;
  for(i=0; i<num; i++)    
  {
    if( strcmp(list.array[i].name, artist) == 0 )
    {
      list.array[i].count++;  
      status = vsMultipleVotes;
      genToken(token);
      wlog(artist, token);
      marshal_submitvote(status, stat, token);
      uList.uids[uList.num++] = au->aup_uid;
      return TRUE;
    }
  }
  
  if ( strcpy(list.array[num].name, artist) == NULL )
    goto errout;

  list.array[num].count = 1;
  list.num++;
  status = vsVoted; 
  genToken(token);
  marshal_submitvote(status, stat, token);
  wlog(artist, token);
  uList.uids[uList.num++] = au->aup_uid;
  return TRUE;

errout:
  status = vsOtherError;
  marshal_submitvote(status, stat, "");
  return FALSE;  
}



bool_t 
results_1_svc(void *x, NetMessage *msg, struct svc_req *rqstp)
{
   int i;
 
   if ( rqstp->rq_cred.oa_flavor == AUTH_SYS )
   {
      struct authsys_parms *au;

      au = (struct authsys_parms *) rqstp->rq_clntcred;

      /*Check user's gid*/
      if ( au->aup_gid == GID )
      {
        marshal_results(&list, msg);
        return TRUE;
      }
   }

   return FALSE;
}


int
votesys_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result,
                     caddr_t result)
{
  xdr_free(xdr_result, result); 
  return 1; 
}
